package processor;

import com.google.auto.service.AutoService;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;

@SupportedAnnotationTypes("processor.HelloWorld")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

    Messager messager;

    public synchronized void init(ProcessingEnvironment processingEnv) {
        messager = processingEnv.getMessager();
        super.init(processingEnv);
    }

    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
            JavacElements elementUtils = (JavacElements) processingEnv.getElementUtils();
            TreeMaker treeMaker = TreeMaker.instance(context);
            for (Element element : roundEnv.getElementsAnnotatedWith(HelloWorld.class)) {
                JCTree.JCMethodDecl jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);

                treeMaker.pos = jcMethodDecl.pos;
                jcMethodDecl.body = treeMaker.Block(0, List.of(
                        treeMaker.Exec(
                                treeMaker.Apply(
                                        List.<JCTree.JCExpression>nil(),
                                        treeMaker.Select(
                                                treeMaker.Select(
                                                        treeMaker.Ident(
                                                                elementUtils.getName("System")
                                                        ),
                                                        elementUtils.getName("out")
                                                ),
                                                elementUtils.getName("println")
                                        ),
                                        List.<JCTree.JCExpression>of(
                                                treeMaker.Literal("Hello, world!!!")
                                        )
                                )
                        ),
                        jcMethodDecl.body,
                        treeMaker.Exec(
                                treeMaker.Apply(
                                        List.<JCTree.JCExpression>nil(),
                                        treeMaker.Select(
                                                treeMaker.Select(
                                                        treeMaker.Select(
                                                                treeMaker.Select(
                                                                        treeMaker.Ident(elementUtils.getName("java")),
                                                                        elementUtils.getName("lang")
                                                                ),
                                                                elementUtils.getName("System")
                                                        ),
                                                        elementUtils.getName("out")
                                                ),
                                                elementUtils.getName("println")
                                        ),
                                        List.<JCTree.JCExpression>of(
                                                treeMaker.Literal("Hello, world!!!")
                                        )
                                )
                        )
                ));
            }
            return false;
        }
    }